package com.eclipse.training.extensions.views;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

import com.eclipse.training.extensions.Activator;
import com.eclipse.training.extensions.ui.ViewLabelProvider;
import com.eclipse.training.models.BaseModelElement;
import com.eclipse.training.models.ModelContainer;

public class TrainingView extends ViewPart {

	private static final String KEY_SORT = "sort.state"; //$NON-NLS-1$

	/**
	 * The ID of the view as specified by the extension.
	 */
	public static final String ID = "com.eclipse.training.extensions.views.TrainingView"; //$NON-NLS-1$

	private TableViewer viewer;
	private Action actionSort;
	private Action doubleClickAction;

	private boolean sortState;

	private Action actionRename;

	private ISelectionListener pageSelectionListener;

	/**
	 * The constructor.
	 */
	public TrainingView() {
	}

	/**
	 * Restore previous state
	 */
	@Override
	public void init(IViewSite site, IMemento memento) throws PartInitException {
		super.init(site, memento);
		if (memento != null && memento.getBoolean(KEY_SORT) != null)
			sortState = memento.getBoolean(KEY_SORT);
		else
			sortState = false;
	}

	/**
	 * Create the viewer and initialize it. Typically this method simply calls
	 * more finely grained methods that draw part controls.
	 */
	public void createPartControl(Composite parent) {
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL);
		viewer.setContentProvider(new ArrayContentProvider());
		viewer.setLabelProvider(new ViewLabelProvider());

		if (sortState)
			viewer.setSorter(new ViewerSorter());
		else
			viewer.setSorter(null);

		// Create the help context id for the viewer's control
		PlatformUI.getWorkbench().getHelpSystem()
				.setHelp(viewer.getControl(), Activator.PLUGIN_ID + ".viewer"); //$NON-NLS-1$

		hookListeners();
		makeActions();
		hookContextMenu();
		hookDoubleClickAction();
		contributeToActionBars();
	}

	/**
	 * Add a post selection listener in order to consume the selection from
	 * TreeViewer
	 */
	private void hookListeners() {

		pageSelectionListener = new ISelectionListener() {

			@Override
			public void selectionChanged(IWorkbenchPart part,
					ISelection selection) {
				if (part == TrainingView.this)
					return;

				if (!(selection instanceof IStructuredSelection))
					return;

				IStructuredSelection sel = (IStructuredSelection) selection;
				Object element = sel.getFirstElement();
				if (element instanceof ModelContainer) {
					viewer.setInput(((ModelContainer) element).getElements());
					viewer.refresh();
				}
			}
		};
		getSite().getPage().addPostSelectionListener(pageSelectionListener);

	}

	private void hookContextMenu() {
		MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				TrainingView.this.fillContextMenu(manager);
			}
		});
		Menu menu = menuMgr.createContextMenu(viewer.getControl());
		viewer.getControl().setMenu(menu);
		getSite().registerContextMenu(menuMgr, viewer);
	}

	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalPullDown(bars.getMenuManager());
		fillLocalToolBar(bars.getToolBarManager());
	}

	private void fillLocalPullDown(IMenuManager manager) {
		manager.add(actionSort);
		manager.add(new Separator());
	}

	private void fillContextMenu(IMenuManager manager) {
		manager.add(actionSort);
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
		manager.add(actionRename);
	}

	private void fillLocalToolBar(IToolBarManager manager) {
		manager.add(actionSort);
	}

	private void makeActions() {
		actionSort = new Action("Sort Action", IAction.AS_CHECK_BOX) {

			public void run() {

				/*
				 * Enable/Disable sorter
				 */
				if (isChecked()) {
					sortState = true;
					viewer.setSorter(new ViewerSorter());
				} else {
					sortState = false;
					viewer.setSorter(null);
				}
				viewer.refresh();
			}
		};
		actionSort.setText("Sort Action");
		actionSort.setChecked(sortState);
		actionSort.setToolTipText(Messages.TrainingView_6);
		actionSort.setImageDescriptor(Activator.getDefault()
				.getImageDescriptor(Activator.IMAGE_SORT));

		actionRename = new Action(Messages.TrainingView_7, IAction.AS_PUSH_BUTTON) {

			public void run() {								
				BaseModelElement selection = (BaseModelElement) ((IStructuredSelection) viewer
						.getSelection()).getFirstElement();
				if (selection != null) {
					InputDialog dialog = new InputDialog(Display.getDefault()
							.getActiveShell(), Messages.TrainingView_8,
							Messages.TrainingView_9, selection.getName(), null);
					dialog.setBlockOnOpen(true);
					if (dialog.open() == Dialog.OK) {

						String value = dialog.getValue();
						if (value.compareTo(selection.getName()) != 0) {
							selection.setName(value);
							viewer.refresh(selection);
						}
					}
				}
			}
		};
		actionRename.setText(Messages.TrainingView_10);
		actionRename.setToolTipText(Messages.TrainingView_11);

		doubleClickAction = new Action() {
			public void run() {
				ISelection selection = viewer.getSelection();
				Object obj = ((IStructuredSelection) selection)
						.getFirstElement();
				showMessage(Messages.TrainingView_12 + obj.toString());
			}
		};
	}

	private void hookDoubleClickAction() {
		viewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				doubleClickAction.run();
			}
		});
	}

	private void showMessage(String message) {
		MessageDialog.openInformation(viewer.getControl().getShell(),
				Messages.TrainingView_13, message);
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		viewer.getControl().setFocus();
	}

	/**
	 * Save view state
	 */
	@Override
	public void saveState(IMemento memento) {
		memento.putBoolean(KEY_SORT, sortState);
		super.saveState(memento);
	}

	/**
	 * Remove post selection listener
	 */
	@Override
	public void dispose() {
		getSite().getPage().removePostSelectionListener(pageSelectionListener);
		super.dispose();
	}
}